package com.iot.core.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Calendar;
import java.util.Date;

/**
 * @ClassName AESUtil
 * @Description AES加密解密工具类
 * @Author DuWei
 * @Date 2019/2/25 17:23
 **/
public class AESUtil {
    private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);
    private static final String defaultCharset = "UTF-8";
    public static final String VIPARA = "0102030405060708";
    private static final String KEY_AES = "AES";

    public static final String AES_KEY_DATE_PATTERN = "yyyyMMddHH:00:00";

    /**
     * 平台内部授权信息解密，采用时间作key进行解密，时间格式为："yyyyMMddHH:00:00"，考虑时间因素第一次解密失败会向前回滚1个小时尝试解密
     * @param encrypted
     * @return
     */
    public static String authDecrypt(String encrypted) {
        //第一次解密
        Date now = new Date();
        String key = DateUtils.format(now,AES_KEY_DATE_PATTERN);
        try {
            String decryptInfo = AESUtil.decrypt(encrypted, key);
            if (StringUtils.isBlank(decryptInfo)) {
                //采用当前时间前一个小时作为Key来尝试解密
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(now);
                calendar.add(Calendar.HOUR_OF_DAY,-1);
                key = DateUtils.format(calendar.getTime(),AES_KEY_DATE_PATTERN);
                decryptInfo = AESUtil.decrypt(encrypted, key);
            }
            return decryptInfo;
        } catch (Exception e) {
            logger.error("AES 密文处理异常", e);
            return null;
        }
    }

    /**
     * 平台内部授权信息加密
     * @param key
     * @return
     */
    public static String authEncrypt(String key) {
        String date = DateUtils.format(new Date(),AES_KEY_DATE_PATTERN);
        return AESUtil.encrypt(date+"_"+key,date);
    }

    public static String encrypt(String cleartext, String dataPassword) {
        try {
            IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
            SecretKeySpec key = new SecretKeySpec(dataPassword.getBytes(), KEY_AES);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
            byte[] encryptedData = cipher.doFinal(cleartext.getBytes(defaultCharset));
            return parseByte2HexStr(encryptedData);
        } catch (Exception e) {
            logger.error("AES 密文处理异常", e);
        }
        return null;
    }

    public static String decrypt(String encrypted, String dataPassword){
        try {
            byte[] byteMi = parseHexStr2Byte(encrypted);
            IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
            SecretKeySpec key = new SecretKeySpec(dataPassword.getBytes(), KEY_AES);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);
            byte[] decryptedData = cipher.doFinal(byteMi);
            return new String(decryptedData,defaultCharset);
        } catch (Exception e) {
            logger.error("AES 密文解密失败");
        }
        return null;
    }

    /**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }
    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
    public static void main(String[] args) {
        try {
            //27beb3e044a611e9120a5cf4e92e85ba
            //00000000-4748-1bf3-0000-000173dsuytg
            System.out.println(authEncrypt("ffffffff-e5e7-af84-ffff-ffffc28d0e61"));
            //System.out.println(decrypt("93A4C9D2D0CD450DF3F9D58DCE3A75B0CF15CC40AF29D167650B3AF879B3E54E0966D3CC13546F41BF474B72840163CA83D3D088BDD8A25CEE9D37097E833A3E","2019050520:00:00"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

